home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UUPC3 / MAC_SPEC / UNIX_LIB / SIO.C < prev    next >
Text File  |  1992-02-10  |  11KB  |  606 lines

  1. /*            sio.c
  2.  
  3.  
  4.                 Serial I/O for rz/sz
  5.  
  6.  
  7.                 Copyright (c) 1986 Stuart Lynne
  8.  
  9.                 June 1986
  10.  
  11.                 Modified for Think C
  12.                 
  13.                 Sak Wathanasin 1989
  14.  
  15.             Portions Copyright ⌐ David Platt, 1992, 1991.  All Rights Reserved
  16.             Worldwide.
  17.  
  18. */
  19. #include "sio.h"
  20.  
  21. #include <stdio.h>
  22. #ifndef  THINK_C
  23. #include <pb.h>
  24.  
  25. #include <osutil.h>
  26.  
  27. /* #include <max/macglobals.h> */
  28. #include <max/debug.h>
  29. #include <max/asc.h>
  30. #else   THINK_C
  31. # include "dcp.h"
  32. #endif   THINK_C
  33.  
  34. #ifndef FALSE
  35. # define FALSE 0
  36. #endif FALSE
  37. #ifndef TRUE
  38. # define TRUE 1
  39. #endif TRUE
  40.  
  41. #ifdef Upgrade
  42. static int g_setting;
  43. #endif Upgrade
  44.  
  45. struct SIOPort curPort={0};
  46.  
  47. #ifdef DOASYNC
  48.  
  49. static struct async_write *asyncout;
  50. static int async_head, async_tail, async_pending;
  51. static int allowInterrupts = FALSE;
  52. static int interruptOccurred = FALSE;
  53. static int sleepLimit = 3;
  54.  
  55. #endif
  56.  
  57. #define baud38400 1
  58.  
  59. struct {
  60.     unsigned int baudr;
  61.     int speedcode;
  62. } speeds[] = {
  63.     300,    baud300,
  64.     600,    baud600,
  65.     1200,    baud1200,
  66.     2400,    baud2400,
  67.     4800,    baud4800,
  68.     9600,    baud9600,
  69.     19200,    baud19200,
  70.     38400,     baud38400,
  71.     57600,     baud57600,
  72.     0,
  73. };
  74.  
  75. static char otherIn[] = "\p.?In";
  76. static char otherOut[] = "\p.?Out";
  77.  
  78. static unsigned int
  79. getspeed(code)
  80. {
  81.     register n;
  82.  
  83.     for (n=0; speeds[n].baudr; ++n)
  84.         if (speeds[n].speedcode == code)
  85.             return speeds[n].baudr;
  86.     return -1;
  87. }
  88.  
  89.  
  90. static unsigned
  91. getbaud(code)
  92.     char *code; {
  93.     register n;
  94.     register long int Baudrate;
  95.     
  96.     Baudrate = atol(code);
  97.     
  98.     for(n=0 ; speeds[n].baudr ; ++n)
  99.         if(speeds[n].baudr == Baudrate)
  100.             return(speeds[n].speedcode);
  101.     return -1;
  102. }
  103.  
  104.  
  105.  
  106. SIOInit ( whichport, speed )
  107. char * whichport;
  108. char * speed;
  109. {
  110.     char i;
  111.     SerShk    handshake;
  112.     int setting, baudCode, speedVal;
  113.     int err;
  114.     long int bytes;
  115.  
  116.     /*  fprintf( stderr, "sioinit %s %s\n", whichport, speed ); /* */
  117.     
  118.     if ( 
  119.         strncmp( whichport, ".a", 2 ) == 0 || 
  120.         strncmp( whichport, "a",1 ) == 0 ||
  121.         strcmp( whichport, "modem") == 0
  122.         ) 
  123.     {
  124.         curPort.in = AIN;
  125.         curPort.out = AOUT;
  126.     }
  127.     else if (
  128.         strncmp( whichport, ".b", 2 ) == 0 || 
  129.         strncmp( whichport, "b", 1 ) == 0 ||
  130.         strcmp( whichport, "printer") == 0 
  131.         ) 
  132.     {
  133.         curPort.in = BIN;
  134.         curPort.out = BOUT;
  135.     }
  136.     else if (strlen(whichport) == 1 && whichport[0] >= 'c' && whichport[0] <= 'z') {
  137.         otherIn[2] = otherOut[2] = whichport[0];
  138.         curPort.in = otherIn;
  139.         curPort.out = otherOut;
  140.     } else if (strlen(whichport) == 2 && whichport[0] == '.' && whichport[1] >= 'c' && whichport[1] <= 'z') {
  141.         otherIn[2] = otherOut[2] = whichport[1];
  142.         curPort.in = otherIn;
  143.         curPort.out = otherOut;
  144.     } else
  145.         return( -1 );
  146.  
  147.     baudCode = getbaud(speed);
  148.     if (baudCode == -1) {
  149.         fprintf(stderr, "Baud rate %s is not supported or not recognized\n", speed);
  150.         return (-1);
  151.     }
  152.     
  153.     speedVal = getspeed(baudCode);
  154.     
  155.     if (speedVal <= 9600) {
  156.         sleepLimit = 3;
  157.     } else if (speedVal < 57600) {
  158.         sleepLimit = 1;
  159.     } else {
  160.         sleepLimit = 0;
  161.     }
  162.  
  163.     if ((err = OpenDriver ( (StringPtr)curPort.in,  &curPort.refin )) !=0 ) {
  164.         fprintf( stderr, "Err: %d\n", err);
  165. #ifdef    DEBUG
  166.         debugMsg ( ctop( curPort.in ) );
  167. #endif
  168.         SysBeep (20); 
  169.         return( -1 );
  170.     }
  171.  
  172.     
  173.     if ((err=OpenDriver ( (StringPtr)curPort.out, &curPort.refout )) !=0 ) {
  174.         fprintf( stderr, "Err: %d\n", err);
  175. #ifdef    DEBUG
  176.         debugMsg ( ctop( curPort.out ) );
  177. #endif
  178.         SysBeep (20); 
  179.         return( -1 );
  180.     }
  181.     
  182.     SIOHandshake( FALSE, FALSE, FALSE, XON, XOFF );
  183.     SIOSetting( speed, noParity, stop10, data8 );
  184.  
  185. #ifdef DOASYNC
  186.  
  187.     bytes = BUFFERS * sizeof (struct async_write);
  188.  
  189.     asyncout = (struct async_write *) NewPtr(bytes);
  190.     if (asyncout) {
  191.         memset(asyncout, 0, bytes);
  192.     }
  193.     async_head = async_tail = 0;
  194.     allowInterrupts = interruptOccurred = FALSE;
  195.  
  196. #endif
  197.  
  198.     return( 0 );
  199. }
  200.  
  201. SIOSpeed( speed )
  202. char * speed;
  203. {
  204.     SIOSetting( speed, curPort.parity, curPort.stopbits, curPort.databits );
  205. }
  206.  
  207. SIOHandshake ( fInx, fXOn, fCTS, xOn, xOff )
  208. {    
  209.     int err;
  210.     
  211.     curPort.handshake.fInX = fInx;
  212.     curPort.handshake.fXOn = fXOn;
  213.     curPort.handshake.fCTS = fCTS;
  214.  
  215.     curPort.handshake.xOn = xOn;
  216.     curPort.handshake.xOff = xOff;
  217.     /* handshake.fXOn = TRUE; */
  218.     
  219.     curPort.handshake.errs = 0;
  220.     curPort.handshake.evts = 0;
  221.  
  222.     if ((err=SerHShake (curPort.refin, &curPort.handshake ))!=0 ) {
  223.         fprintf( stderr, "Err: %d\n", err);
  224. #ifdef    DEBUG
  225.         debugMsg ("\PSerHShake error");
  226. #endif
  227.         SysBeep (20); 
  228.     }
  229. }
  230.  
  231. SIOSetting( speed, parity, stopbits, databits )
  232. char * speed;
  233. {
  234.     int err;
  235.     int setting;
  236.     
  237.     curPort.baud = getbaud(speed);
  238.     curPort.parity = parity;
  239.     curPort.stopbits = stopbits;
  240.     curPort.databits = databits;
  241.     
  242.     setting = curPort.baud + parity + stopbits + databits;
  243. #ifdef Upgrade
  244.     /* store current settings in a global area */
  245.     g_setting = setting;
  246. #endif Upgrade
  247.  
  248.     if ((err=SerReset(curPort.refin, setting))!=0 )  {
  249.         fprintf( stderr, "Err: %d\n", err);
  250. #ifdef    DEBUG
  251.         debugMsg ("\PSerReset error");
  252. #endif
  253.         SysBeep (20);
  254.     }    
  255. }
  256.  
  257. SIOInBuffer ( buf, size )
  258. char * buf;
  259. int size;
  260. {
  261.     curPort.inbuffer = buf;
  262.     curPort.insize = size;
  263.     SerSetBuf( curPort.refin, buf, size ); 
  264. }
  265.  
  266. SIOOutBuffer ( buf, size )
  267. char * buf;
  268. int size;
  269. {
  270.     curPort.outbuffer = buf;
  271.     curPort.outsize = size;
  272.     SerSetBuf( curPort.refout, buf, size ); 
  273. }
  274.  
  275.  
  276. SIOClose ( dtr )
  277. {
  278.     CntrlParam SIOpb;
  279.     
  280.     long count;
  281.  
  282.     if ( dtr != 0 && curPort.refin != 0) {
  283.         /* drop DTR */
  284.         SIOpb.ioCompletion = NULL;
  285.         SIOpb.ioRefNum = curPort.refin;
  286.         SIOpb.csCode = 18;
  287.         PBControl ((ParmBlkPtr)&SIOpb, FALSE);
  288.     }
  289.     
  290.     SIOInBuffer( NULL, 0 );
  291.     SIOOutBuffer( NULL, 0 );
  292.     if (curPort.refin != 0) CloseDriver( curPort.refin );
  293.     if (curPort.refout != 0)CloseDriver( curPort.refout );
  294.     if (asyncout) {
  295.         DisposPtr(asyncout);
  296.         asyncout = NULL;
  297.     }
  298.     async_head = async_tail = async_pending = 0;
  299.     curPort.refin = curPort.refout = 0;
  300. }
  301.  
  302.  
  303. sfflushout ()
  304. {
  305. }
  306.  
  307. SIOSetFlowCtl(flag)
  308. int flag;
  309. {
  310.     SerShk flowRec;
  311.     flowRec.fXOn = flag;
  312.     flowRec.fInX = flag;
  313.     flowRec.fCTS = 0;    /* bad juju to try... input handshake might be DTR */
  314.     flowRec.xOn =  0x11;
  315.     flowRec.xOff = 0x13;
  316.     flowRec.errs = flowRec.evts = 0;
  317.     SerHShake(curPort.refin, &flowRec);
  318.     SerHShake(curPort.refout, &flowRec);
  319. }
  320.  
  321. SIOAllowInterrupts(flag)
  322. int flag;
  323. {
  324.     int oldFlag;
  325.     oldFlag = allowInterrupts;
  326.     allowInterrupts = flag;
  327.     interruptOccurred &= flag;
  328.     return oldFlag;
  329. }
  330.  
  331. SIOInterrupt()
  332. {
  333.     interruptOccurred = TRUE;
  334. }
  335.  
  336. SIOPurge ()
  337. {    /*
  338.     char        ch;
  339.  
  340.     while (sread (&ch, 1, 1) == 1);
  341.     
  342.     */
  343.     (void) KillIO(curPort.refin);
  344.     (void) KillIO(curPort.refout);
  345. }
  346.  
  347. SIOPutchar ( ch )
  348. char ch;
  349. {
  350.     /*fprintf(stderr, "<%02x>", ch);*/
  351.     return( putu ( &ch, 1, curPort.refout ) );    
  352. }
  353.  
  354. SIOWrite ( buf, count )
  355. char * buf;
  356. int count;
  357. {
  358.     return( putu (buf, count, curPort.refout) );
  359. }
  360.  
  361. int SIOAvail()
  362. {
  363.     long int count;
  364.     (void)SerGetBuf(curPort.refin, &count);
  365.     return count;
  366. }
  367.  
  368.  
  369. SIOWStr ( st )
  370. char * st;
  371. {
  372.     return( putu (st, strlen(st), curPort.refout) );
  373. }
  374.  
  375. #define    Ticks            (*(long *)            0x16a)
  376.     
  377.  
  378. /* timeout is in tenths of a second */
  379. int SIORead ( byt, mincount, maxcount, tenths )
  380. char * byt;
  381. int    mincount;
  382. int     maxcount;
  383. long int tenths;
  384. {
  385.     long    timea;
  386.     short    actCount;
  387.  
  388.     int        i;
  389.     
  390.     timea = Ticks;
  391.     tenths *= 6;
  392.     /* fprintf (stderr, "Read  m= %d T= %ld", maxcount, Ticks  );/**/
  393.     do {
  394.         actCount = getn (byt, mincount, maxcount, curPort.refin );
  395.  
  396.         if (actCount > 0) {
  397.             /* fprintf (stderr, "  OK: %d\n", actCount);/**/
  398.             return actCount;
  399.             }
  400.         
  401.         if (allowInterrupts && interruptOccurred) {
  402.             return -1;
  403.         }
  404.             
  405.     } while ((long)(Ticks - timea) < tenths);
  406.     
  407.     /* fprintf (stderr, "  Timed out: t= %d\n  T:%ld", tenths, Ticks );/**/
  408.     return -1;
  409.     }
  410.  
  411. srdchk ()
  412. {
  413.     long count;
  414.  
  415.     (void)SerGetBuf(curPort.refin, &count);    
  416.     if (count >= 1) 
  417.         return TRUE;
  418.     else 
  419.         return FALSE;
  420. }
  421.  
  422. #ifdef BREAK
  423. ssendbrk(bnulls) {
  424.     int setting;
  425.     
  426. # ifdef Upgrade
  427.     setting = baud300 + noParity + stop10 + data8;
  428. # else Upgrade
  429.     setting = curPort.baud + noParity + stop10 + data8;
  430. # endif Upgrade
  431.  
  432.     if(SerReset(curPort.refin, setting)) {
  433. # ifdef    DEBUG
  434.         debugMsg("\PSerReset error");
  435. # endif
  436.         SysBeep(20);
  437.     }    
  438.  
  439.     swrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", bnulls*2);
  440.  
  441. # ifdef Upgrade
  442.     setting = g_setting;
  443. # else Upgrade
  444.     setting = curPort.baud + noParity + stop10 + data8;
  445. # endif Upgrade
  446.  
  447.     if(SerReset(curPort.refin, setting)) {
  448. # ifdef    DEBUG
  449.         debugMsg("\PSerReset error");
  450. # endif
  451.         SysBeep(20);
  452.     }    
  453.    return;
  454. }
  455. #endif BREAK
  456.  
  457.  
  458. /*     Fill array *cp with characters from serial buffer, starting
  459.     at 0, until cmax. Return actual chars read. Don't read unless
  460.     at least cmin are available.
  461. */
  462. int getn ( cp, cmin, cmax, refin )
  463. char *cp;
  464. register int cmax, cmin;
  465. register short refin;
  466. {    
  467.     ParamBlockRec    SIOpb;
  468.     register        ParmBlkPtr    pbp = &SIOpb;
  469.  
  470.     long            count;
  471.     int                firstTry = TRUE;
  472.  
  473.     /* fprintf( stderr, " %d", cmin ); /* */
  474.     
  475. tryit:
  476.     (void)SerGetBuf(refin, &count);
  477.     SIOpb.ioParam.ioReqCount = count;
  478.     if ( count >= cmin) {
  479.         if ( count >  cmax) 
  480.             SIOpb.ioParam.ioReqCount = (long) cmax;
  481.         printmsg(4, "Read %ld", SIOpb.ioParam.ioReqCount);
  482.            SIOpb.ioParam.ioRefNum = refin;
  483.            SIOpb.ioParam.ioBuffer = (Ptr) cp;
  484.            SIOpb.ioParam.ioPosMode = 0;
  485.         PBRead (&SIOpb, FALSE);
  486.         count = SIOpb.ioParam.ioActCount;
  487. #ifdef MULTIFINDER
  488.         if (Ticks-Last_Check_Event >= MF_DELAY)  
  489.           if (Check_Events(0)) {
  490.             if (Main_State == Abort_Program) {
  491.                 SIOClose(TRUE);
  492.                 exit(-1);
  493.             }
  494.           }
  495. #endif 
  496.         }
  497.     else {
  498. #ifdef MULTIFINDER
  499.         /* the data hasn't been received, ok to delay a bit */
  500.         if (Ticks-Last_Check_Event >= MF_DELAY)  
  501.           if (Check_Events(sleepLimit)) {
  502.             if (Main_State == Abort_Program)  {
  503.                 SIOClose(TRUE);
  504.                 exit(-1);
  505.             }
  506.            }
  507. #endif 
  508.         count = 0;
  509.         if (firstTry) {
  510.             firstTry = FALSE;
  511.             goto tryit;
  512.         }
  513.     }
  514.         
  515.  
  516.     return( (int)count );
  517. }
  518.  
  519.  
  520. static ParamBlockRec          pb = {0};
  521.  
  522. int SIOWriteBusy()
  523. {
  524.     if (pb.ioParam.ioResult == 1) {
  525.         return TRUE;
  526.     } else {
  527.         return FALSE;
  528.     }
  529. }
  530.     
  531.  
  532. int putu( c, count, refout )
  533. char     *c;
  534. short    count;
  535. short    refout;
  536. {
  537.     register ParmBlkPtr    pbp = &pb;
  538.     int spin;
  539.     int isAsync;
  540.  
  541. #ifdef DOASYNC
  542.     isAsync = (asyncout != NULL) && (count <= BUFSIZE);
  543.     if (isAsync) {
  544.         spin = TRUE;
  545.         do {
  546.             if (async_pending == 0) {
  547.                 spin = FALSE;
  548.             } else {
  549.                 pbp = &asyncout[async_tail].pb;
  550.                 if (pbp->ioParam.ioResult != 1) {
  551.                     async_pending --;
  552.                     async_tail = (async_tail + 1) % BUFFERS;
  553.                 } else {            
  554. #ifdef MULTIFINDER
  555.                     if (Ticks-Last_Check_Event >= MF_DELAY) 
  556.                       if (Check_Events(0)) 
  557.                         if (Main_State == Abort_Program)  {
  558.                               SIOClose(TRUE);
  559.                             exit(-1);
  560.                         }
  561. #endif
  562.                     if (async_pending < BUFFERS) {
  563.                         spin = FALSE;
  564.                     }
  565.                 }
  566.             }
  567.         } while (spin);
  568.         
  569.         pbp = &asyncout[async_head].pb;
  570.         memcpy(asyncout[async_head].buf, c, (long) count);
  571.         
  572.         pbp->ioParam.ioCompletion = NULL;
  573.         pbp->ioParam.ioRefNum = refout;
  574.         pbp->ioParam.ioBuffer = asyncout[async_head].buf;
  575.         pbp->ioParam.ioReqCount = count;
  576.         pbp->ioParam.ioPosMode = 0;
  577.         
  578.         PBWrite(pbp, TRUE);
  579.  
  580.         async_head = (async_head + 1) % BUFFERS;
  581.         async_pending ++;
  582.     } else {
  583. #endif
  584.         pb.ioParam.ioCompletion = NULL;
  585.         pb.ioParam.ioRefNum = refout;
  586.         pb.ioParam.ioBuffer = c;
  587.         pb.ioParam.ioReqCount = count;
  588.         pb.ioParam.ioPosMode = 0;
  589.       
  590.         PBWrite(&pb, FALSE );
  591. #ifdef DOASYNC
  592.     }
  593. #endif
  594.     
  595. #ifdef MULTIFINDER
  596.         if (Ticks-Last_Check_Event >= MF_DELAY) 
  597.           if (Check_Events(0)) 
  598.             if (Main_State == Abort_Program)  {
  599.                   SIOClose(TRUE);
  600.                 exit(-1);
  601.             }
  602. #endif 
  603.  
  604.     return( (short) pb.ioParam.ioActCount );
  605. }
  606.